#include <Ape/IO/FS/Path.h>
#include <Ape/Collections/StringList.h>
#include <Ape/Exception.h>
#include <Ape/IO/Console.h>

namespace Ape {
	namespace IO {
		namespace FS {
			using Ape::Collections::StringList;
			
			Path::Path() : m_OriginalString (L"") {}
			Path::Path (const String& s)
					: m_OriginalString (s)
			{}
			Path::Path (const Path& other)
					: Object (other),
					m_OriginalString (other.m_OriginalString)
			{}
			Path::Path (const wchar_t* wcs)
					: m_OriginalString (wcs)
			{}
			
			Path::~Path() {}
			
			bool Path::IsAbsolute() const {
				if (m_OriginalString.get_Length() == 0)
					return false;
				return m_OriginalString.At (0) == L'/';
			}
			
			void Path::get_Parts (StringList& parts) const {
				m_OriginalString.Split (L'/', parts);
			}
			
			const Path Path::get_Parent() const {
				StringList parts;
				get_Parts (parts);
				if (parts.get_Count() == 0) {
					throw Exception (L"Cannot get parent: already at top level");
				}
				parts.FetchLast();
				
				String result (parts.Join (L"/") );
				if (IsAbsolute() )
					return L"/" + result;
				else
					return result;
			}
			
			const String Path::ToString() const {
				return m_OriginalString;
			}
			
			void Path::_Dump (bool verbose) const {
				using Ape::IO::StdOut;
				using Ape::IO::NewLine;
				
				Object::_Dump (verbose);
				
				DUMP_NON_V_TYPE;
				
				DUMP_PROPERTY (L"Orig. String", m_OriginalString)
				DUMP_PROPERTY (L"Is Absolute", IsAbsolute() )
			}
			
			Path Path::Combine (const Path& p1, const Path& p2) {
				String s1 = p1.ToString();
				String s2 = p2.ToString();
				if (s1.IsEmpty() )
					return s2;
				if (s1.At (s1.get_Length() - 1) == L'/') {
					s1 = s1.Substring (0, s1.get_Length() - 1);
				}
				if (s2.IsEmpty() )
					return s1;
				if (s2.At (0) == L'/') {
					//s2 = s2.Substring (1);
					return s2;
				}
				
				return s1 + L"/" + s2;
			}
			
			const String Path::get_Name() const {
				StringList parts;
				get_Parts (parts);
				if (parts.get_Count() == 0)
					throw Exception (L"Cannot get name-part of top level path");
					
				return parts.FetchLast();
			}
			
			const String Path::get_Suffix() const {
				String sName = get_Name();
				StringList parts;
				sName.Split (L'.', parts);
				if (parts.get_Count() < 2) {
					return L"";
				}
				else {
					return parts.FetchLast();
				}
			}
			const String Path::get_NoSuffix() const {
				String sName = get_Name();
				StringList parts;
				sName.Split (L'.', parts);
				if (parts.get_Count() < 2) {
					return sName;
				}
				else {
					parts.FetchLast();
					return parts.Join (L".");
				}
			}
			
		}
	}
}
